#pragma once
#include <iostream>
#include <semaphore.h>

using std::cout;
using std::endl;

const int gcap = 5;

template <typename T>
class circularQueue
{
public:
    circularQueue() : _consumer(0), _producer(0)
    {
        sem_init(&_sem_room, 0, gcap);
        sem_init(&_sem_data, 0, 0);
        //难道下标不要进行初始化的吗？？？要的 //error
    }

    //P封装的可以更优雅一些：只要将sem_wait封装进去就可以了，同理V操作也是

    void P_Data(T *out)
    {
        sem_wait(&_sem_data);
        *out = _buffer[_consumer];
        _consumer++;
        _consumer %= gcap;
    }

    void P_Room(T &in)
    {
        sem_wait(&_sem_room);
        _buffer[_producer] = in;
        _producer++;
        _producer %= gcap;
    }

    void V_Data()
    {
        sem_post(&_sem_data);
    }

    void V_Room()
    {
        sem_post(&_sem_room);
    }

    ~circularQueue()
    {
        sem_destroy(&_sem_room);
        sem_destroy(&_sem_data);
    }

private:
    sem_t _sem_room; // 信号量 -- 空间资源，生产者关心
    sem_t _sem_data; // 信号量 -- 数据资源，消费者关心
    int _consumer;   // 消费者的下标
    int _producer;   // 生产者的下标
    T _buffer[gcap];
};